package com.nulldev.util.uri.yt.legacy;

import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

import com.nulldev.util.io.IOUtils;
import com.nulldev.util.java.JVMUtil;
import com.nulldev.util.java.swing.nGetUI;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.math.MathUtil;
import com.nulldev.util.other.ArrayUtils;
import com.nulldev.util.uri.URIUtil;
import com.nulldev.util.uri.http.HTTP;
import com.nulldev.util.uri.nget.nGet;

@Deprecated
public class YTDownloader {
	public int times = 3;
	private final Logger log = LoggerFactory.getLogger();
	private URL yt_URL;
	private HashSet<String> set = new HashSet<String>();
	@Deprecated
	private List<String> audio_set = new ArrayList<String>();
	@Deprecated
	private List<String> video_set = new ArrayList<String>();
	@Deprecated
	private List<String> av_set = new ArrayList<String>();
	
	private LinkedList<YTIndex> index = new LinkedList<YTIndex>();

	public YTDownloader(String url_in) {
		if (url_in.contains("hooktube.com")) {
			log.warn("HookTube link detected, correcting that for you. :)");
			url_in = url_in.replaceAll("hooktube.com", "youtube.com");
		}
		final URL url = URIUtil.safeCreate(url_in);
		if (!URIUtil.isValid(url.toExternalForm()) || !url.toExternalForm().contains("youtube.com")) {
			throw new RuntimeException("URL was not valid!");
		}else {
			this.yt_URL = url;
		}
	}
	
	@Deprecated
	public void man_downloadIndex() {
		log.warn("You are running a deprecated function, things won't work so well.");
		try {
			final HttpURLConnection conn = (HttpURLConnection) this.yt_URL.openConnection();
			
			final String out = IOUtils.getStringFromInputStream(conn.getInputStream());
			conn.setRequestProperty("User-agent", "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0 " + MathUtil.randInt(0, 10000000));
			final String[] list = out.split("url=");
			for(String i: list){
				if (i.startsWith("https")) {
					set.add(i.split(",")[0]);
				}
			}
		    String url = null, itag = null, quality_label = null, type = null;
			for(String i: set){
					String temp = i;
					temp = temp.replace("\\", "\\\\");
					for(String sdata : temp.split("\\\\")){
						if(sdata.startsWith("https"))
							url = sdata;
					}
					if(url!=null){
						if(url.startsWith("https")){
							url = url.split(" ")[0];
							url = URLDecoder.decode(url, "UTF-8");
							if(url.contains("mime="))
								type = (url.split("mime=")[1]).split("&")[0];
							if(url.contains("itag"))
								itag = (url.split("itag=")[1]).split("&")[0];
							if(url.contains("&gir=yes")){
								if(type.startsWith("video")) {
									video_set.add(url+"\ntype: "+type+"\nitag: "+itag);
								} else if(type.startsWith("audio")) {
									audio_set.add(url+"\ntype: "+type+"\nitag: "+itag);
								}
							}
							else {
								av_set.add(url+"\ntype: "+type+"\nitag: "+itag);
							}
						}
					}
			}
			log.info("Downloaded index!");
		}catch (Exception e) {
			log.error("Failed to download index.", e);
		}
	}
	
	private int maxRuns = this.times;
	private int runs = 0;
	public void fetchIndex() {
		try {
			final HttpURLConnection conn = (HttpURLConnection) this.yt_URL.openConnection();
			conn.setRequestProperty("User-agent", "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0 " + MathUtil.randInt(0, 10000000));
			final String out = IOUtils.getStringFromInputStream(conn.getInputStream());
			conn.disconnect();
			
			final String[] list = out.split("url=");
			for(String i: list){
				if (i.startsWith("https")) {
					set.add(i.split(",")[0]);
				}
			}
		    String url = null, itag = null, quality_label = null, type = null;
			for(String i: set) {
					if (i.contains("use_cipher_signature=True")) {
						log.warn("fetchIndex() -> URL contains use_cipher=True, attempting bypass...");
						Thread.sleep(500L);
					}
					String temp = i;
					temp = temp.replace("\\", "\\\\");
					for(String sdata : temp.split("\\\\")){
						if(sdata.startsWith("https"))
							url = sdata;
					}
					if(url!=null){
						if(url.startsWith("https")){
							url = url.split(" ")[0];
							url = URLDecoder.decode(url, "UTF-8");
							if(url.contains("mime="))
								type = (url.split("mime=")[1]).split("&")[0];
							if(url.contains("itag"))
								itag = (url.split("itag=")[1]).split("&")[0];
							if(url.contains("&gir=yes")){
								if(type.startsWith("video")) {
									final YTIndex iX = new YTIndex(YTIndexTYPE.VIDEO, itag, url+"\ntype: "+type+"\nitag: "+itag);
									if (!this.index.contains(iX)) {
										this.index.add(iX);
									}
									//video_set.add(url+"\ntype: "+type+"\nitag: "+itag);
								} else if(type.startsWith("audio")) {
									//audio_set.add(url+"\ntype: "+type+"\nitag: "+itag);
									final YTIndex iX = new YTIndex(YTIndexTYPE.AUDIO, itag, url+"\ntype: "+type+"\nitag: "+itag);
									if (!this.index.contains(iX)) {
										this.index.add(iX);
									}
								}
							}
							else {
								//av_set.add(url+"\ntype: "+type+"\nitag: "+itag);
								final YTIndex iX = new YTIndex(YTIndexTYPE.AUDIO_VIDEO, itag, url+"\ntype: "+type+"\nitag: "+itag);
								if (!this.index.contains(iX)) {
									this.index.add(iX);
								}
							}
						}
					}
			}
			
			int count = 0;
			for (final YTIndex x : this.index) {
				if (x.getType() == YTIndexTYPE.AUDIO) {
					count += 1;
					x.setIDX("[1-" + count + "]");
				}else if (x.getType() == YTIndexTYPE.VIDEO) {
					count += 1;
					x.setIDX("[2-" + count + "]");
				}else if (x.getType() == YTIndexTYPE.AUDIO_VIDEO) {
					count += 1;
					x.setIDX("[3-" + count + "]");
				}
				x.setQuality(getQuality((x.getData().split("\n")[2]).split(": ")[1]));
				if (x.getQuality().contains("MP4")) {
					x.setExtension("mp4");
				}else if (x.getQuality().contains("m4a")) {
					x.setExtension("m4a");
				}else if (x.getQuality().contains("webm") || x.getQuality().contains("WebM")) {
					x.setExtension("webm");
				}else if (x.getQuality().contains("ogg")) {
					x.setExtension("ogg");
				}else if (x.getQuality().contains("3GP")) {
					x.setExtension("3gp");
				}else if (x.getQuality().contains("opus")) {
					x.setExtension("opus");
				}else if (x.getQuality().contains("vp9")) {
					x.setExtension("vp9");
				}else if (x.getQuality().contains("m4v")) {
					x.setExtension("m4v");
				}
			}
			if (this.runs > this.maxRuns) {
				log.info("Downloaded index!");
				log.info("Queried data is now updated.");
				this.runs = 0;
			}else {
				log.info("Checking for more options...PLEASE WAIT [" + (this.runs + 1) + "/" + (this.maxRuns + 1) + "]");
				this.runs += 1;
				this.fetchIndex();
			}
		}catch (Exception e) {
			log.error("Failed to download index.", e);
		}
	}
	
	public void debug_printIndex() {
		for (final YTIndex x : this.index) {
			if (x.toString() != "false") {
				synchronized (System.out) {
					synchronized (System.err) {
						System.out.println(x.toString());
					}
				}
			}
		}
	}
	
	@Deprecated
	public void debug_printIndex_legacy() {
		log.warn("You are running a deprecated function, things won't work so well.");
	    int count = 0;
	    log.binfo("audio Link: ");
	    for(String s: audio_set){
	      count = count + 1;
	      //System.out.println(URLDecoder.decode(s,"UTF-8"));
	      log.binfo("[1-"+count+"] " + (s.split("\n")[1]).replace("%2F","\\") + " " + getQuality((s.split("\n")[2]).split(": ")[1]));
	    }
	    count = 0;
	    log.binfo("video Link: ");
	    for(String s: video_set){
	      count = count + 1;
	      //System.out.println(URLDecoder.decode(s,"UTF-8"));
	      log.binfo("[2-"+count+"] " + (s.split("\n")[1]).replace("%2F","\\") + " " + getQuality((s.split("\n")[2]).split(": ")[1]));
	    }
	    count = 0;
	    log.binfo("audio/video Link: ");
	    for(String s: av_set){
	      count = count + 1;
	      //System.out.println(URLDecoder.decode(s,"UTF-8"));
	      log.binfo("[3-"+count+"] " + (s.split("\n")[1]).replace("%2F","\\") + " " + getQuality((s.split("\n")[2]).split(": ")[1]));
	    }
	}
	
	public void download(final YTIndex index) {
		if (index == null) {
			log.error("Variable 'index' is null! Stopping...");
			return;
		}
		System.out.println(index.getData());
		try {
			log.info("Checking if the value is safe...");
			int avd = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[0]);
			int dindex = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[1]);
			log.info("Value is safe, carrying on...");
		}catch (Exception e) {
			log.error("Failed to download, invalid index.");
			return;
		}
	    String type;
	    URL ylink_download;
		final int avd = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[0]);
		final int dindex = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[1]);
		type = index.getData().split("\n")[1];
		ylink_download = URIUtil.safeCreate(index.getData().split("\n")[0]);
//		if (avd == 3) {
//			try {
//			      ylink_download = URIUtil.safeCreate((av_set.get(dindex-1)).split("\n")[0]);
//			      type = (av_set.get(dindex-1)).split("\n")[1];	
//			}catch (Exception e) {
//				log.error("Error reached. Stopping...", e);
//				return;
//			}
//		}else if (avd == 2) {
//			try {
//			      ylink_download = URIUtil.safeCreate((video_set.get(dindex-1)).split("\n")[0]);
//			      type = (video_set.get(dindex-1)).split("\n")[1];
//			}catch (Exception e) {
//				log.error("Error reached. Stopping...", e);
//				return;
//			}
//		}else if (avd == 1) {
//			try {
//			      ylink_download = URIUtil.safeCreate((audio_set.get(dindex-1)).split("\n")[0]);
//			      type = (audio_set.get(dindex-1)).split("\n")[1];
//			}catch (Exception e) {
//				log.error("Error reached. Stopping...", e);
//				return;
//			}
//		}else {
//			log.error("Invalid index given, try again. [STOPPED]");
//			return;
//		}
		final nGet get = new nGet(ylink_download);
		get.setLogDownloadStatus(true);
		//get.overrideName("videoplayback_" + MathUtil.randInt(0, 10000000));
		if (!index.getExtension().equals("N/A")) {
			get.overrideName("videoplayback." + index.getExtension());
		}else {
			get.overrideName("videoplayback");
		}
		get.download();
		final nGetUI nu = nGetUI.main(get);
		get.waitTillFinished();
		synchronized (get) {
			log.info("Done.");
			nu.setVisible(false);
			nu.dispose();
		}
		
		if (get.FAILED && nu.isVisible()) {
			nu.setVisible(false);
			nu.dispose();
		}
		
		if (this.exitOnFinish) {
			JVMUtil.exit();
		}
	}
	
	public void download(final YTIndex... indexes) {
		if (indexes == null) {
			log.error("Variable 'indexes' was null! Stopping...");
			return;
		}
		log.info("Starting extended download... [" + indexes.length + " sources]");
		int source = 0;
		for (final YTIndex index : indexes) {
			source += 1;
			log.info("Downloading from source '" + source + "'...");
			if (index.getQuality().contains("N/A")) {
				log.warn("Downloading an unknown source... use at your own risk. [debugID: " + index.getQuality() + "]");
			}
			boolean cont = true;
			if (index == null) {
				log.error("Variable 'index' is null! Stopping...");
				cont = false;
			}
			try {
				log.info("Checking if the value is safe...");
				int avd = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[0]);
				int dindex = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[1]);
				log.info("Value is safe, carrying on...");
			}catch (Exception e) {
				log.error("Failed to download, invalid index.");
				cont = false;
			}
			if (cont) {
			    String type;
			    URL ylink_download;
				final int avd = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[0]);
				final int dindex = Integer.parseInt(index.getIDX().substring(1, index.getIDX().length() - 1).split("-")[1]);
				type = index.getData().split("\n")[1];
				ylink_download = URIUtil.safeCreate(index.getData().split("\n")[0]);
				final nGet get = new nGet(ylink_download);
				get.setLogDownloadStatus(true);
				//get.overrideName("videoplayback_" + MathUtil.randInt(0, 10000000));
				if (!index.getExtension().equals("N/A")) {
					get.overrideName("videoplayback." + index.getExtension());
				}else {
					get.overrideName("videoplayback");
				}
				get.download();
				if (get.FAILED) {
				}else {
					final nGetUI nu = nGetUI.main(get);
					get.waitTillFinished();
					synchronized (get) {
						log.info("Done.");
						nu.setVisible(false);
						nu.dispose();
					}
				
					if (this.exitOnFinish && !get.FAILED) {
						JVMUtil.exit();
					}
					if (!get.FAILED) {
						break;
					}else {
						if (nu.isVisible()) {
							nu.setVisible(false);
							nu.dispose();
						}
						if (ylink_download != null) {
							log.warn("Download of file failed.");
						}
					}
				}
			}
		}//System.out.println
	}
	
	@Deprecated
	public void download_legacy(final String index) {
		log.warn("You are running a deprecated function, things won't work so well.");
		try {
			log.info("Checking if the value is safe...");
			int avd = Integer.parseInt(index.split("-")[0]);
			int dindex = Integer.parseInt(index.split("-")[1]);
			log.info("Value is safe, carrying on...");
		}catch (Exception e) {
			log.error("Failed to download, invalid index.");
			return;
		}
	    String type;
	    URL ylink_download;
		final int avd = Integer.parseInt(index.split("-")[0]);
		final int dindex = Integer.parseInt(index.split("-")[1]);
		if (avd == 3) {
			try {
			      ylink_download = URIUtil.safeCreate((av_set.get(dindex-1)).split("\n")[0]);
			      type = (av_set.get(dindex-1)).split("\n")[1];	
			}catch (Exception e) {
				log.error("Error reached. Stopping...", e);
				return;
			}
		}else if (avd == 2) {
			try {
			      ylink_download = URIUtil.safeCreate((video_set.get(dindex-1)).split("\n")[0]);
			      type = (video_set.get(dindex-1)).split("\n")[1];
			}catch (Exception e) {
				log.error("Error reached. Stopping...", e);
				return;
			}
		}else if (avd == 1) {
			try {
			      ylink_download = URIUtil.safeCreate((audio_set.get(dindex-1)).split("\n")[0]);
			      type = (audio_set.get(dindex-1)).split("\n")[1];
			}catch (Exception e) {
				log.error("Error reached. Stopping...", e);
				return;
			}
		}else {
			log.error("Invalid index given, try again. [STOPPED]");
			return;
		}
		//System.out.println("avd = " + avd);
		//System.out.println("dindex = " + dindex);
		final nGet get = new nGet(ylink_download);
		get.setLogDownloadStatus(true);
		//get.overrideName("videoplayback_" + MathUtil.randInt(0, 10000000));
		get.overrideName("videoplayback");
		get.download();
		log.info("Done.");
		
		if (this.exitOnFinish) {
			JVMUtil.exit();
		}
	}
	
	public void debug_printIndex_pure() {
		log.info("Printing index...");
		for (final String s : av_set) {
			System.out.println(s);
		}
		log.info("Done.");
	}
	
	public static String getQuality(final String x)
	{
	    if(x.equals("5"))
	        return "normal, 240p, FLV, 320x240";
	    else if(x.equals("17"))
	        return "normal, 144p, 3GP, 176x144";
	    else if(x.equals("18"))
	        return "normal, 360p, MP4, 640x360";
	    else if(x.equals("22"))
	        return "normal, 720p, MP4, 1280x720";
	    else if(x.equals("34"))
	        return "normal, 360p, FLV, 640x360";
	    else if(x.equals("35"))
	        return "normal, 480p, FLV, 854x480";
	    else if(x.equals("36"))
	        return "normal, 240p, 3GP, 320x240";
	    else if(x.equals("37"))
	        return "normal, 1080p, MP4, 1920x1080";
	    else if(x.equals("38"))
	        return "normal, 3072p, MP4, 4096x3072";
	    else if(x.equals("43"))
	        return "normal, 360p, WebM, 640x360";
	    else if(x.equals("44"))
	    	return "normal, 480p, WebM, 854x480";
	    else if(x.equals("45"))
	    	return "normal, 720p, WebM, 1280x720";
	    else if(x.equals("46"))
	    	return "normal, 1080p, WebM, 1920x1080";
	    else if(x.equals("82"))
	    	return "normal, 360p, MP4, 640x360-3D";
	    else if(x.equals("83"))
	    	return "normal, 480p, MP4, 640x480-3D";
	    else if(x.equals("84"))
	    	return "normal, 720p, MP4, 1280x720-3D";
	    else if(x.equals("100"))
	    	return "normal, 360p, WebM, 640x360-3D";
	    else if(x.equals("102"))
	    	return "normal, 720p, WebM, 1280x720-3D";


	    else if(x.equals("133"))
	        return "video only, 240p, m4v, 426x240";
	    else if(x.equals("134"))
	        return "video only, 360p, m4v, 640x360";
	    else if(x.equals("135"))
	        return "video only, 480p, m4v, 854x480";
	    else if(x.equals("136"))
	        return "video only, 720p, m4v, 1280x720";
	    else if(x.equals("137"))
	        return "video only, 1080p, m4v, 1920x1080";
	    else if(x.equals("138"))
	        return "video only, 3072p, m4v, 4096x3072";


	    else if(x.equals("139"))
	        return "audio only, 48k, m4a";
	    else if(x.equals("140"))
	        return "audio only, 128k, m4a";
	    else if(x.equals("141"))
	        return "audio only, 256k, m4a";
	    else if(x.equals("160"))
	        return "video only, 144p, m4v, 256x144";
	    else if(x.equals("167"))
	        return "video only, 480p, webm, 640x480";
	    else if(x.equals("168"))
	        return "video only, 480p, webm, 854x480";
	    else if(x.equals("169"))
	        return "video only, 720p, webm, 1280x720";
	    else if(x.equals("170"))
	        return "video only, 1080p, webm, 1920x1080";
	    else if(x.equals("171"))
	        return "audio only,  128k, ogg";
	    else if(x.equals("172"))
	        return "audio only, 192k, ogg";
	    else if(x.equals("242"))
	        return "normal, 240p, webm, 360x240";
	    else if(x.equals("243"))
	        return "normal, 360p, webm, 480x360";
	    else if(x.equals("244"))
	        return "normal, 480p, webm, 640x480";
	    else if(x.equals("245"))
	        return "normal, 480p, webm, 640x480";
	    else if(x.equals("246"))
	        return "normal, 480p, webm, 640x480";
	    else if(x.equals("247"))
	        return "normal, 480p, webm, 720x480";
	    else if(x.equals("248"))
	        return "normal, 1080p, webm,  1920x1080";
	    else if(x.equals("256"))
	        return "audio, 192k, m4a";
	    else if(x.equals("258"))
	        return "audio, 320k, m4a";
	    else if(x.equals("264"))
	        return "video only, 1080p, m4v, 1920x1080";
	    else if (x.equals("278"))
	    	return "video only, 144p, vp9";
	    else if (x.equals("299")) 
	    	return "video only, mp4, 60fps, 1080p";
	    else if (x.equals("251"))
	    	return "audio only, opus, 32bits";
	    else if (x.equals("298"))
	    	return "video only, mp4, 60fps, 720p";
	    else if (x.equals("302")) 
	    	return "video only, vp9, 60fps, 720p";
	    else if (x.equals("250")) 
	    	return "audio only, opus, 32bits, alt";
	    else if (x.equals("303"))
	    	return "video only, vp9, 60fps, 1080p";
	    else if (x.equals("249"))
	    	return "audio only, opus, 32bits, alt2";
	    else
	        return "N/A [" + x + "]";
	}

	public YTIndex by(final String string) {
		final String toCheck = "[" + string + "]";
		for (final YTIndex yt : this.index) {
			if (yt.getIDX().equals(toCheck)) {
				return yt;
			}
		}
		return null;
	}

	public YTIndex byQuality(final String string) {
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().equals(string)) {
				return yt;
			}
		}
		return null;
	}
	
	public YTIndex byQuality(final YTQuality val) {
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().equals(val.getData())) {
				return yt;
			}
		}
		return null;
	}
	
	public YTIndex byQualityF(final YTQuality val, final YTQuality val1) {
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().equals(val.getData())) {
				return yt;
			}
		}
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().equals(val1.getData())) {
				return yt;
			}
		}
		return null;
	}
	
	public YTIndex byQualityI(final YTQuality... vals) {
		for (final YTQuality quality : vals) {
			for (final YTIndex yt : this.index) {
				if (yt.getQuality().equals(quality.getData())) {
					return yt;
				}
			}
		}
//		for (final YTIndex yt : this.index) {
//			if (yt.getQuality().equals(val.getData())) {
//				return yt;
//			}
//		}
//		for (final YTIndex yt : this.index) {
//			if (yt.getQuality().equals(val1.getData())) {
//				return yt;
//			}
//		}
		return null;
	}

	private boolean exitOnFinish;
	public void exitOnFinish() {
		this.exitOnFinish = !exitOnFinish;
	}
	
	public YTIndex[] all() {
		return ArrayUtils.linkedListToArray((LinkedList<YTIndex>) this.index.clone());
	}
	
	public YTIndex[] all_NoOpus() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (!yt.getQuality().contains("opus")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}

	public YTIndex[] allAudio() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("audio only")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}
	
	public YTIndex[] allAudio_NoOpus() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("audio only") && !yt.getQuality().contains("opus")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}
	
	public YTIndex[] allVideo() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("video only")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}

	public YTIndex[] allStandard() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("normal") && yt.getQuality().contains("MP4")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}
	
	public YTIndex[] allUnknown() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("N/A [")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}

	/**
	 * Returns <b>Video</b> only streams in 60FPS, you need to manually download an audio stream. <br>
	 * This is a limitation of Youtube's CDN.
	 * @return YTIndex[]
	 */
	public YTIndex[] _60fps_videos() {
		final ArrayList<YTIndex> out = new ArrayList<YTIndex>();
		for (final YTIndex yt : this.index) {
			if (yt.getQuality().contains("60fps") && yt.getQuality().contains("video only")) {
				out.add(yt);
			}
		}
		return ArrayUtils.arrayListToArray(out);
	}
	
	public static boolean canBeDownloaded(final String url) {
		try {
			final YTDownloader dl = new YTDownloader(url);
			dl.log.infoEnabled = false;
			dl.times = 2;
			dl.fetchIndex();
			return URIUtil.getResponseCode(URIUtil.safeCreate(dl.byQualityI(YTQuality.AUDIO_M4A_128K, YTQuality.AUDIO_M4A_192K, YTQuality.AUDIO_M4A_256K).getData().split("\n")[0])) == HTTP.OK;
		}catch (Exception e) {
			return false;
		}
	}
	
	public static int canBeDownloadedI(final String url) {
		try {
			final YTDownloader dl = new YTDownloader(url);
			dl.log.infoEnabled = false;
			dl.times = 2;
			dl.fetchIndex();
			return URIUtil.getResponseCode(URIUtil.safeCreate(dl.byQualityI(YTQuality.AUDIO_M4A_128K, YTQuality.AUDIO_M4A_192K, YTQuality.AUDIO_M4A_256K).getData().split("\n")[0]));
		}catch (Exception e) {
			return 404;
		}
	}
}
